package com.example.redisdemo.contro;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/redis")
public class RedisController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @GetMapping("/stock")
    public void redisTest() {
        String uuid = UUID.randomUUID().toString();
        // 加锁
        while (Boolean.FALSE.equals(this.redisTemplate.opsForValue().setIfAbsent("lock", uuid, 3, TimeUnit.SECONDS))) {
            // 重试，循环
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Boolean aBoolean = this.redisTemplate.hasKey("stock");
            if(Boolean.FALSE.equals(aBoolean)) {
                this.redisTemplate.opsForValue().setIfAbsent("stock","5000",10,TimeUnit.SECONDS);
            }
            // 查询库存信息
            String stock = redisTemplate.opsForValue().get("stock");

            // 判断库存是否充足
            if(stock != null && stock.length() != 0) {
                Integer st = Integer.valueOf(stock);
                if(st > 0) {
                    // 扣减库存
                    redisTemplate.opsForValue().set("stock",String.valueOf(--st));
                }
            }
        }finally {
            // 先判断再解锁，使用LUA脚本实现分布式锁，来保证原子性
//            String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
            String script = "if redis.call('get',KEYS[1]) == ARGV[1] " +
                    "then " +
                    "   return redis.call('del',KEYS[1]) " +
                    "else " +
                    "   return 0 " +
                    "end";
            this.redisTemplate.execute(new DefaultRedisScript<>(script,Long.class), Collections.singletonList("lock"),uuid);


            // 有缺陷
//            if(StringUtils.equals(this.redisTemplate.opsForValue().get("lock"),uuid)) {
//                this.redisTemplate.delete("lock");
//            }

        }
    }
}
